668: Push-down of arithmetics before source operations#967
668: Push-down of arithmetics before source operations#967b-m-f wants to merge 44 commits intodaphne-project:mainfrom
Conversation
069cf4d to
b38c03b
Compare
|
I am currently facing an issue while trying to push down the mlir::daphne::FillOp pushDownFillIntoEwLog(mlir::daphne::FillOp fillOp, mlir::daphne::EwLogOp op, mlir::Value scalar, mlir::PatternRewriter &rewriter) {
auto fillValue = fillOp.getArg();
auto height = fillOp.getNumRows();
auto width = fillOp.getNumCols();
mlir::daphne::EwLogOp newLog = rewriter.create<mlir::daphne::EwLogOp>(op.getLoc(), fillValue, scalar);
return rewriter.create<mlir::daphne::FillOp>(op.getLoc(), op.getResult().getType(), newLog, width, height);In order to get to the Unfortunately my MLIR output with looks as follows: I believe that Have I introduced this problem when creating my All code is checked into the latest commit. Any help is appreciated - I would like to make sure I am not having some big misunderstanding before implementing the remaining push-downs for unary and binary ops. |
6e49f8c to
b6756e7
Compare
|
Also https://github.com/daphne-eu/daphne/blob/main/test/api/cli/distributed/DistributedTest.cpp is failing if I mark Is there another safe way to remove the OP without setting |
|
Yes, the result of Your To solve the problem, you should either (a) specify an unknown type ( |
|
Regarding the failing If we haven't solved the problem in the distributed runtime by the time we merge your PR, we will change this test file and create an issue for the problem. |
|
Just took a brief look at the code, and I'm wondering if implementing this push down optimization as canonicalization on every operator that we want to push down, for every operator that can be pushed into, is the right place to do that. It seems quite hard to maintain. @b-m-f @pdamme What do you think about an interface based approach? With that interface, every op that wants to can implement it: That can either be done in the TableGen definition directly or similar to our current interfaces in DAPHNE. And with that we have a rewrite pass on, for example, the struct FillOpPushdownPattern : public OpRewritePattern<FillOp> {
LogicalResult matchAndRewrite(FillOp fillOp,
PatternRewriter &rewriter) const override {
auto pushdownOp = dyn_cast< PushDownOpInterface >(fillOpArgument);
if (!pushdownOp)
return failure();
// Call the interface functions to:
// 1. Check if it's actually a scalar like is currently happening in the canonicalize method
// 2. Call the `createScalarValue` method that creates the correct, pushed down, computation
auto newFill = rewriter.create<FillOp>(result of pushed down computation...);
rewriter.replaceOp(fillOpArgument, newFill);
}
}Additionally, instead of having a New operators that can be pushed down now only need to implement a single interface and source operators that want to enable this do it with the other interface. I feel like this approach could eliminate all this duplicated code that's currently in the draft, and makes it quite easy to extend push down optimizations to other operations by implementing the corresponding interface. What do you think? |
|
I wanted to implement all pushdown operations mentioned in the issue and then refactor from there - to have tests in place etc. ( duplication was easier for me l, as I am still getting used to the framework ). |
|
All pushdown combinations mentioned in the issue are now implemented in the verbose style. Here are few notes for the next Zoom session:
|
|
Unfortunately I can not seem to make any progress with the interface approach. I have added a new commit with the changes I assume to be necessary in order to get The whole trace is very long, but I believe this to be the gist: https://mlir.llvm.org/docs/Interfaces/#interface-methods states: Do I also need to generate a new trait in the Edit: Not sure if this is fine - since this in an exercise for AMLS - but maybe you can integrate FillOp for Add onto this branch (basically the example you gave) and I take it from there for the rest? |
316895c to
b2897e7
Compare
|
@philipportner I was not able to get it running using interfaces. Instead I discussed with @pdamme to use C++ template functions as well as Traits to get rid of all the duplications. Traits
This is now complete and pushed here for review. The individual Operations still have to enable Canonicalization with |
f4106ca to
60b6d94
Compare
Just as a quick follow-up: I fixed the problem with the incorrect type inference in the custom builder of the elementwise binary ops today in b55d1a8. |
pdamme
left a comment
There was a problem hiding this comment.
Thanks for this contribution, @b-m-f! Simplification rewrites that avoid unnecessary matrix intermediate results by pushing down certain operations (especially elementwise unary and binary functions) into source ops like FillOp, RandMatrixOp, and SeqOp are very welcome. Your overall approach of integrating these rewrites as canonicalizations of the elementwise ops while using some custom traits and delegating the work to one helper function per arity of elementwise operations is a reasonable trade-off to avoid code duplication for now. (We could try to refactor it to use MLIR interfaces later.) Overall, your code already looks good to me, but there are a few pitfalls in the details and, thus, a few points need to be addressed before we can merge this PR:
Required changes: (must be addressed before we can merge this PR)
- Please document each push-down-related trait with a short description in
src/ir/daphneir/DaphnePushDownTraits.h. It should become clear what these traits mean, such that other developers know when to attach them to an operation. You can take inspiration fromsrc/ir/daphneir/DaphneInferTypesOpInterface.h. - In
pushDownUnary(), the case forRandMatrixOpfollowed byEwAbsOphas some issues that need to be fixed:- It uses
CompilerUtils::isConstant(), but doesn’t check if the SSA values are really constant. The first element of the returned pair must be examined. The second element must only be used if the first element istrue. - When
minandmaxare both non-negative, there is no need to create a newRandMatrixOp, you can just replace theEwAbsOpby the existingRandMatrixOp. - I think the case for
minandmaxboth negative should check ifmaxValue <= 0(notminValue <= 0). - Please make sure that the rewrite is applied when
minandmaxare the same, e.g.,abs(rand(2, 2, -77, -77, 0.8, -1))(and add test cases for it).
- It uses
- In
pushDownBinary(), the case forRandMatrixOp:EwMulOpandEwDivOpmust not be pushed beforeRandMatrixOpfor integral value types. For instance,rand(1, 1, 1, 3, 1.0, -1) * 100should only return values in {100, 200, 300}, but currently, it can return any value in [100, 300] (e.g, 123). For floating-point value types, the rewrite should be fine, though. - In
pushDownBinary(), the case forSeqOp: Shouldn’tEwDivOpalso have thePushDownWithIntervalUpdatetrait? For instance,seq(2, 6, 2) / 2should return[1, 2, 3], but currently it returns[1, 3]because the increment is not updated. Please fix and add a test case. - Please fix this bug (and add test cases):
rand(2, 3, 100, 200, 1.0, -1) + 10should return a 2x3 matrix, but returns a 3x2 matrix.
Optional changes: (recommended, but not critical for merging)
- Do we really need the
PushDowntrait? The fact that an op supports push-down in some way is already encoded in the canonicalization function of the op callingtryPushDown(). I think removing this trait would make the code simpler overall (less checks etc., less things one could forget when supporting more ops). - Do we really need
tryPushDown()? It seems to me like an unnecessary indirection. Instead, we could directly callpushDownUnary()orpushDownBinary()in the concrete ops’ canonicalization function. To support push-down for another elementwise unary/binary function, it would currently not suffice to add a canonicalization function that callstryPushDown(), one also has to add the op intryPushDown(), which could easily be forgotten. - In
pushDownUnary(), the case forRandMatrixOptreats ops with the traitPushDownLinearin a special way. However, this trait is only attached to elementwise binary ops inDaphneOps.td. One consequence it that this code path doesn’t get tested. I suggest adding an example of an elementwise unary op that behaves linearly, such asEwMinusOpas in-rand(...). - Feel free to use
rewriter.replaceOpWithNewOp()instead ofrewriter.create()followed byrewriter.replaceOp(). It’s shorter. - Should the trait
PushDownIntervalUpdatebe renamed toPushDownIncrementUpdate? As far as I understand this trait is about updating the increment argument ofSeqOp.
I hope these comments are helpful for improving this PR. Feel free to share your thoughts.
|
Thanks for the review @pdamme ! From the top of my head I remember there being an issue with EwDivOp and SeOp if the division is not resulting in an integer, but I will double check and can also try to do a check using mod denominator == 0. |
1893830 to
77ad54e
Compare
|
Hi @pdamme, I have added all suggestions into the MR. There is one inconsistency with I have left the failing tests included for now instead of accepting the new results - in order to discuss whether they should be accepted or if I should just remove the The results are valid even though they differ from main. This is because the For me this still seems fine, as the results are in the correct range, but for absolute consistency with the non pushed down version this might not be desired. Just let me know and I will either:
|
b3f09a1 to
3647c5d
Compare
|
I see that the build is failing, which is unexpected and seems to be related to Maybe I forgot to push a change? 🤔 |
Signed-off-by: bob@sodawa.com <bob@sodawa.com>
Signed-off-by: bob@sodawa.com <bob@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
… of the randomly generated matrix Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
…tion on pushdown Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
… be buggy - does not output doubles Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
… for PushDown Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
…bs case. Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
…pushdown Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
…wn in integer space, adds docs to tryPushDown Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
…value checks are performed safely Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
… are integers Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
…pdate Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
3647c5d to
58f19f9
Compare
|
Hi @pdamme, I am confused as to why the build is failing in the CI. My steps:
The working commit this branch builds on is c6f7563 . Do you have an idea which change since then could interfere with Maybe b55d1a8 ? Unfortunately I can not continue on this today ( I just came back to Berlin and many things are in the backlog ), but i'll try to allocate an hour per day this week. |
Signed-off-by: Maximilian Ehlers <daphnevm@sodawa.com>
|
My assumption from the previous comment seems to have been correct. I updated the calls to The questions for the tests still remain before merge. Please let me know whether this "change" in behavior is acceptable. |
Changed the branch to integrate upstream changes into my fork easier.
Still working on #668
Previous discussions: #966